#include "ShpTerrainFileManager.h"
#include "shapelib/shapefil.h"
#include "../geom/TerrainModel.h"
#include "../geom/PolyMesh.h"
#include "../geom/PolyModel.h"
#include "../geom/PolyObject.h"
#include <limits>
#include "VibModelFileManager.h"

using namespace dataengine;

bool ShpTerrainFileManager::canLoadFile() throw()
{
	SHPHandle hSHP = SHPOpen(m_filename.c_str(), "rb" );
	if(hSHP == NULL)
		return false;

	SHPClose(hSHP);

	return true;
}




geom::TerrainModel ShpTerrainFileManager::loadFile()
{
	geom::TerrainModel result;

	DBFHandle hDBF = DBFOpen( m_filename.c_str(), "rb" );
	if( hDBF == NULL )
		throw DataException("Could not load Terrain file");

	if( DBFGetFieldCount(hDBF) != 3 )
	{
		DBFClose(hDBF);
		throw DataException("DBF file does not have the expected number of fields (3)");
	}

	// Find max and min in every direction
	double maxDirs[3];
	double minDirs[3];
	maxDirs[0] = maxDirs[1] = maxDirs[2] = numeric_limits<double>::min();
	minDirs[0] = minDirs[1] = minDirs[2] = numeric_limits<double>::max();

	for(int iRecord = 0; iRecord < DBFGetRecordCount(hDBF); iRecord++ )
	{
		for(int i = 0; i < 3; i++ )
		{
			double d = DBFReadDoubleAttribute( hDBF, iRecord, i ) / 10000.0;
			if(d > maxDirs[i])
				maxDirs[i] = d;
			if(d<minDirs[i])
				minDirs[i] = d;
		}
	}

	float maxDist = 0;
	for(int i=0;i<3;i++)
		if(maxDirs[i] - minDirs[i] > maxDist)
			maxDist = maxDirs[i] - minDirs[i];


	for(int iRecord = 0; iRecord < DBFGetRecordCount(hDBF); iRecord++ )
	{
		util::Triplet<float> p;
		for(int i = 0; i < 3; i++ )
		{
			double d = DBFReadDoubleAttribute( hDBF, iRecord, i ) / 10000.0;
			p[i] = (d - (maxDirs[i] + minDirs[i])/2) * 100/ (maxDist);
		}
		result.addPoint(geom::Point3D(p[0],p[2],p[1]));
	}
    return result;
}
/*
void triangulateAndSave(const geom::TerrainModel & terrain)
{
	int numPoints = terrain.getNumPoints();
	double * pointsXY = new double[numPoints * 2];
	for(int i=0;i<numPoints;++i)
	{
		util::Triplet<float> p = terrain.getPoint(i);
		pointsXY[2*i] = p[0];
		pointsXY[2*i+1] = p[2];
	}

	int * nod_tri = new int [2*numPoints*3];
	int * triangle_neighbor = new int[2*numPoints*3];
	int tri_num;

	if(error)
	{
		printf("PU PUTA MADRE EN CANOOOOOAAAAAA\n");
		exit(-1);
	}

	geom::PolyMesh mesh;
	for(int i=0;i<numPoints;i++)
	{
		util::Triplet<float> p =  terrain.getPoint(i);
		geom::MeshPoint mp(geom::Point3D(p[0],p[1],p[2]));
		mesh.addPoint(mp);
	}
	for(int i=0; i<tri_num;i++)
	{
		util::Triplet<int> t;
		t[0] = nod_tri[i*3];
		t[2] = nod_tri[i*3+1];
		t[1] = nod_tri[i*3+2];
		mesh.addTriangle(t);
	}

	geom::PolyModel model;
	model.addMesh(mesh);
	geom::PolyObject obj;
	obj.addModel(model);
	dataengine::VibModelFileManager vib("terreno.vib");
	vib.saveToFile(obj);
}
*/
